package com.moodbox.server.common.service.impl;

import cn.hutool.core.collection.ConcurrentHashSet;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.moodbox.server.common.exception.SensitiveWordException;
import com.moodbox.server.common.service.SensitiveWordService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.regex.Pattern;
import java.util.stream.Collectors;

@Slf4j
@Service
public class SensitiveWordServiceImpl implements SensitiveWordService {

    private final Set<String> sensitiveWords = new ConcurrentHashSet<>();

    @Value("${app.sensitive-word.file-path:classpath:sensitive_words.txt}")
    private String sensitiveWordFilePath;

    @Value("${app.sensitive-word.max-word-length:20}")
    private int maxWordLength;

    @Value("${app.sensitive-word.max-total-words:1000}")
    private int maxTotalWords;

    @PostConstruct
    public void init() {
        loadSensitiveWords();
    }

    /**
     * 加载敏感词
     */
    private void loadSensitiveWords() {
        try {
            // 支持classpath和文件系统路径
            List<String> words;
            if (sensitiveWordFilePath.startsWith("classpath:")) {
                // 从classpath加载
                String path = sensitiveWordFilePath.substring("classpath:".length());
                InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(path);
                words = IoUtil.readLines(inputStream, StandardCharsets.UTF_8, new ArrayList<>());
            } else {
                // 从文件系统加载
                words = FileUtil.readLines(new File(sensitiveWordFilePath), StandardCharsets.UTF_8);
            }

            // 过滤空行和注释
            words = words.stream()
                .filter(word -> !StrUtil.isBlank(word) && !word.trim().startsWith("#"))
                .map(String::trim)
                .collect(Collectors.toList());

            // 检查敏感词数量和长度限制
            validateSensitiveWords(words);

            sensitiveWords.addAll(words);
            log.info("成功加载{}个敏感词", sensitiveWords.size());
        } catch (Exception e) {
            log.error("加载敏感词失败", e);
            throw new SensitiveWordException("加载敏感词失败", e);
        }
    }

    /**
     * 验证敏感词列表
     * @param words 敏感词列表
     */
    private void validateSensitiveWords(List<String> words) {
        // 检查敏感词总数
        if (words.size() > maxTotalWords) {
            throw new SensitiveWordException("敏感词总数超过限制：" + maxTotalWords);
        }

        // 检查单个敏感词长度
        for (String word : words) {
            if (word.length() > maxWordLength) {
                throw new SensitiveWordException("敏感词长度超过限制：" + word);
            }
        }
    }

    @Override
    public boolean containsSensitiveWord(String text) {
        if (StrUtil.isBlank(text)) {
            return false;
        }

        return sensitiveWords.stream().anyMatch(text::contains);
    }

    @Override
    public String filterSensitiveWord(String text) {
        if (StrUtil.isBlank(text)) {
            return text;
        }

        String result = text;
        for (String word : sensitiveWords) {
            result = result.replace(word, generateReplacement(word));
        }
        return result;
    }

    @Override
    public void addSensitiveWord(String word) {
        // 参数校验
        if (StrUtil.isBlank(word)) {
            throw new SensitiveWordException("敏感词不能为空");
        }

        // 长度校验
        word = word.trim();
        if (word.length() > maxWordLength) {
            throw new SensitiveWordException("敏感词长度超过限制：" + maxWordLength);
        }

        // 数量校验
        if (sensitiveWords.size() >= maxTotalWords) {
            throw new SensitiveWordException("敏感词总数已达到上限：" + maxTotalWords);
        }

        // 重复性校验
        if (sensitiveWords.contains(word)) {
            log.warn("敏感词已存在：{}", word);
            return;
        }

        sensitiveWords.add(word);
        log.info("添加敏感词：{}", word);
    }

    @Override
    public void removeSensitiveWord(String word) {
        if (StrUtil.isBlank(word)) {
            throw new SensitiveWordException("敏感词不能为空");
        }

        word = word.trim();
        if (sensitiveWords.remove(word)) {
            log.info("移除敏感词：{}", word);
        } else {
            log.warn("尝试移除不存在的敏感词：{}", word);
        }
    }

    /**
     * 生成替换字符
     * @param word 敏感词
     * @return 替换后的字符
     */
    private String generateReplacement(String word) {
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < word.length(); i++) {
            sb.append("*");
        }
        return sb.toString();
    }

    /**
     * 获取当前敏感词列表
     * @return 敏感词列表
     */
    @Override
    public List<String> getSensitiveWords() {
        return new CopyOnWriteArrayList<>(sensitiveWords);
    }
} 